# -*- coding: utf-8 -*-
# created on 2017/2/8


from mathsolver.functions.base import *
from sympy import *
from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve
from mathsolver.functions.zhixian.length import DianToXianJuLi
import itertools
from mathsolver.functions.zhixian.property import GetZhiXianYiBanShi


class PointSymPoint(BaseFunction):
    def solver(self, *args):
        point1, point2, point3 = args
        x_1, y_1 = point1.sympify()
        x_2, y_2 = point2.sympify()
        x_3, y_3 = point3.sympify()
        # x,y = Symbol("xx"), Symbol("yy")
        # ans = solve([Eq(x_1 + x, 2*x_2), Eq(y_1 + y, 2*y_2)], [x, y])
        # target_point = BasePoint({"name":point3.name, "value":[ans[x],ans[y]]})
        # self.steps.append(["因为点%s与%s关于点%s对称" % (point1.name, point3.name, point2.name),
        #                    "点%s" % target_point.printing()])
        self.output.append(BaseEqs([[x_1 + x_3, 2 * x_2], [y_1 + y_3, 2 * y_2]]))
        self.label.add("两点关于一点对称")
        return self


class PointMiddle(BaseFunction):
    def solver(self, *args):
        lin = args[0]

        p1 = self.search(lin.name[0]).sympify()
        p2 = self.search(lin.name[1]).sympify()

        if len(args) > 1:
            pt = args[1]
            xx, yy = pt.sympify()
            eqs = BaseEqs([[2 * xx, p1[0] + p2[0]], [2 * yy, p1[1] + p2[1]]])
            self.steps.append(["因为点%s是%s的中点" % (pt.printing(), lin.printing()), eqs.printing()])
            self.output.append(eqs)
        else:
            self.output.append(BasePoint({"name": "", "value": [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2]}))

        self.label.add("中点公式")
        # self.output.append(BasePoint())
        return self


class PointOrigin(BaseFunction):
    def solver(self, *args):
        name = args[0].name
        self.output.append(BasePoint({"name": name, "value": ["0", "0"]}))
        return self


class PointTrace(BaseFunction):
    @staticmethod
    def get_trace(xx, yy):
        syms = xx.free_symbols
        assert len(syms) == 1
        sym = list(syms)[0]
        points = []
        point_values = []
        for i in range(1, 6):
            points.append(BasePoint({"name": "", "value": [xx.subs({sym: i}), yy.subs({sym: i})]}))
            point_values.append([xx.subs({sym: i}), yy.subs({sym: i})])

        eqs = []
        for x_v, y_v in point_values:
            eqs.append(["(%s -%s)^2 + (%s - %s)^2" % (str(x_v), "aa", str(y_v), "bb"), "rr"])

        ans = MathematicaSolve().solver(BaseEqs(eqs)).output[0].value
        if "Empty" not in str(ans):
            ans = search_multiple(ans, [Symbol("aa"), Symbol("bb"), Symbol("rr")])
            aa, bb, rr = ans.pieces[0][0]
            yuan = BaseYuan([(Symbol("x") - aa) ** 2 + (Symbol("y") - bb) ** 2, rr])
            return yuan

        eqs = []
        for x_v, y_v in point_values:
            eqs.append(["%s/%s + %s/%s" % (str(x_v ** 2), "aa", str(y_v ** 2), "bb"), 1])

        ans = MathematicaSolve().solver(BaseEqs(eqs)).output[0].value
        if "Empty" not in str(ans):
            ans = search_multiple(ans, [Symbol("aa"), Symbol("bb")])
            aa, bb = ans.pieces[0][0]
            if aa > 0 and bb > 0:
                graph = BaseTuoYuan([Symbol("x") ** 2 / aa + Symbol("y") ** 2 / bb, 1])
            else:
                graph = BaseShuangQu([Symbol("x") ** 2 / aa + Symbol("y") ** 2 / bb, 1])
            return graph

        eqs = []
        for x_v, y_v in point_values:
            eqs.append([str(y_v ** 2), "pp*%s" % str(x_v)])

        ans = MathematicaSolve().solver(BaseEqs(eqs)).output[0].value
        if "Empty" not in str(ans):
            pp = ans[Symbol("pp")]
            if isinstance(pp, FiniteSet):
                pp = list(pp)[0]
            return BasePaoWuXian(["y**2", "%s*x" % str(pp)])

    def solver(self, *args):
        pt = args[0]
        xx, yy = pt.sympify()

        values = self.search_multiple([xx, yy])

        if values:
            for value, cond in values.pieces:
                value = [b if isinstance(a, Set) else a for a, b in zip(value, [xx, yy])]
                x_v, y_v = value
                if not x_v.free_symbols and not y_v.free_symbols:
                    continue
                graph = self.get_trace(x_v, y_v)
                self.steps.append(["轨迹方程为 %s" % graph.printing(), ""])
                # trace,cond = piecewise.pieces[0]
                # var = piecewise.var[0]
        elif xx.is_Symbol:
            yy = yy.subs({xx: Symbol("x")})
            assert len(yy.free_symbols) == 1 and yy.has(Symbol("x"))
            self.steps.append(["轨迹方程为 y = %s" % new_latex(yy), ""])
        else:
            graph = self.get_trace(xx, yy)
            # ineqs = BaseIneqs([[Symbol("x"),x],[Symbol("y"),y]])
            # variables = [sym for sym in list(x.free_symbols) + list(y.free_symbols) if str(sym) not in ["x","y"]]
            # self.steps.append(["%s %s" % (latex_symbol["because"], ineqs.printing()),""])
            # ans = MathematicaSolve().solver(ineqs, BaseVariables(variables)).output[0].value
            # # keys,values = ans.items()[0]
            # # is_eqs = {Symbol("x"):1, Symbol("y"):1}
            # # for value in values:
            # #     for k,v in zip(keys, value):
            # #         if isinstance(value, Set) and k in is_eqs:
            # #             is_eqs[k] = 0
            # piecewise = search_multiple(ans, [Symbol("x")])
            self.steps.append(["轨迹方程为 %s" % graph.printing(), ""])

        self.label.add("求轨迹方程")
        self.output.append(graph)
        return self


class PointIsPoint(BaseFunction):
    def solver(self, *args):
        p1, p2 = args
        p1 = p1.sympify()
        p2 = p2.sympify()

        eqs = BaseEqs([[p1[0], p2[0]], [p1[1], p2[1]]])
        self.steps.append(["由题意得 %s" % eqs.printing(), ""])
        self.output.append(eqs)
        return self


class PointsIsPoints(BaseFunction):
    def solver(self, *args):
        points1 = args[0].sympify()
        points2 = args[1].sympify()
        eqs = []
        for p1, p2 in zip(points1, points2):
            for v1, v2 in zip(p1, p2):
                if sympify("%s-%s" % (v1, v2)).free_symbols:
                    eqs.append([v1, v2])

        self.output.append(BaseEqs(eqs))
        return self


class PointIsPoints(BaseFunction):
    def solver(self, *args):
        p1, p2 = args
        p1 = p1.sympify()
        p2 = p2.sympify()
        if not p1[0].free_symbols and p1[0] > 0:
            eqs = BaseEqs([[p1[0], p2[1][0]], [p1[1], p2[1][1]]])
        else:
            eqs = BaseEqs([[p1[0], p2[0][0]], [p1[1], p2[0][1]]])
        self.output.append(eqs)
        return self


class PointOnZuoZhi(BaseFunction):
    def solver(self, *args):
        p = args[0].sympify()
        self.output.append(BaseIneq([p[0], "<", "0"]))
        return self


class PointAxisJuLi(BaseFunction):
    def solver(self, *args):
        pt, axis = args[:2]
        if str(axis.value[0]) == "y":
            value = pt.value[1]
        elif str(axis.value[0]) == "x":
            value = pt.value[0]
        self.output.append(BasePoly("abs(%s)" % str(value)))
        self.label.add("点和坐标轴距离")
        return self


class MultipleDianToXianJuLi(BaseFunction):
    def solver(self, *args):
        points = args[0].value
        zhixians = args[1].value

        juli = set()
        for pt, zhixian in itertools.product(points, zhixians):
            step1 = GetZhiXianYiBanShi().solver(BaseZhiXian(zhixian)).output[0]
            step2 = DianToXianJuLi().solver(BasePoint(pt), step1).output[0]
            juli.add(sympify(step2.value))

        if len(juli) == 1:
            self.output.append(BasePoly(list(juli)[0]))
        else:
            self.output.append(BasePolys(list(juli)))
        self.label.add("点到直线距离")
        return self


class PointOnBanZhou(BaseFunction):
    def solver(self, *args):
        pt, axis, text = args[:3]
        p1, p2 = pt.sympify()
        f1, f2 = axis.sympify()
        ineqs = []
        if str(f1) == "y":
            if "正半轴" in text:
                ineqs.append([p1, ">", "0"])
            elif "负半轴" in text:
                ineqs.append([p1, "<", "0"])

            ineqs.append([p2, 0])

        elif str(f1) == "x":
            if "正半轴" in text:
                ineqs.append([p2, ">", "0"])
            elif "负半轴" in text:
                ineqs.append([p2, "<", "0"])

            ineqs.append([p1, 0])

        obj = BaseIneqs(ineqs)
        self.steps.append(["根据点%s的位置得，%s" % (pt.printing(), obj.printing()), ""])
        self.output.append(obj)
        self.label.add("点在坐标轴上")
        return self


class PointPartial(BaseFunction):
    def solver(self, *args):
        p1, p2 = args[0].sympify()
        text = args[1]
        if "纵坐标" in text:
            value = p2
        elif "横坐标" in text:
            value = p1
        else:
            raise ValueError()
        self.output.append(BasePoly(value))
        self.label.add("点的纵/横坐标")
        return self


class PointsEqSym(BaseFunction):
    def solver(self, *args):
        ax, ay = args[0].sympify()
        bx, by = args[1].sympify()
        m, nn, c = args[2].value
        self.output.append(BaseEqs([[(ay - by) * m, (ax - bx) * nn], [m * (ax + bx) / 2 + nn * (ay + by) / 2 + c, 0]]))
        self.label.add("两点关于直线对称")
        return self


class PointInsideYuan(BaseFunction):
    def solver(self, *args):
        pt, graph = args[:2]
        xx, yy = pt.sympify()
        f1, f2 = graph.sympify()
        ineq = BaseIneq([f1.subs({Symbol("x"): xx, Symbol("y"): yy}), "<", f2.subs({Symbol("x"): xx, Symbol("y"): yy})])
        self.output.append(ineq)
        self.label.add("点在图形内部")
        return self


if __name__ == '__main__':
    pass
